package com.logic.landseaserver.models.changerent.service;

import java.util.*;

import com.logic.landseaserver.common.enums.*;
import com.logic.landseaserver.domain.*;
import com.logic.landseaserver.persistence.read.BillDetailReadMapper;
import com.logic.landseaserver.persistence.read.CustomerCardReadMapper;
import com.logic.landseaserver.persistence.write.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.logic.common.exception.BusinessException;
import com.logic.common.security.SecurityUtils;
import com.logic.landseaserver.common.LandeaConstants;
import com.logic.landseaserver.common.LandeaConstants.AccountStatus;
import com.logic.landseaserver.common.LandseaErrorMessageEnum;
import com.logic.landseaserver.common.exception.LandseaBusinessException;
import com.logic.landseaserver.common.exception.LandseaException;
import com.logic.landseaserver.common.util.ConstantChar;
import com.logic.landseaserver.models.authcode.service.CouponUsedService;
import com.logic.landseaserver.models.prepayment.service.PrepaymentService;
import com.logic.landseaserver.persistence.read.ContractReadMapper;
import com.logic.landseaserver.persistence.read.UrgentReadMapper;
import com.logic.landseaserver.service.IBillService;
import com.logic.landseaserver.service.IContractOfflineService;
import com.logic.landseaserver.service.IContractService;
import com.logic.landseaserver.service.ICustomer;
import com.logic.landseaserver.service.IOffrentPreBill;
import com.logic.landseaserver.service.IProjectAppartment;
import com.logic.landseaserver.ws.dto.ContractDTO;
import com.logic.landseaserver.ws.dto.QueryCouponUesdDTO;
import com.logic.landseaserver.ws.dto.UrgentDTO;
import com.logic.landseaserver.ws.request.ContractNeedDelReq;
import com.logic.landseaserver.ws.request.CreateOffLineContractsReq;
import com.logic.landseaserver.ws.request.RoomDetailReq;
import com.logic.system.service.IConfigurationService;

/**
 * Created by Junny on 2017/12/5.
 * M3 转租
 */
@Service
public class ChangeRentService implements IChangeRentService{

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ContractReadMapper contractReadMapper;

    @Autowired
    private ContractWriteMapper contractWriteMapper;

    @Autowired
    private ICustomer customerService;

    @Autowired
    private IProjectAppartment roomService;

    @Autowired
    private IContractOfflineService contractOfflineService;

    @Autowired
    private CouponUsedService couponUsedService;

    @Autowired
    private IBillService billService;

    @Autowired
    private IContractService contractService;

    @Autowired
    private IOffrentPreBill offrentPreBillService;

    @Autowired
    private ChangeRentPreBillService changeRentPreBillService;

    @Autowired
    private OffRentWriteMapper offRentWriteMapper;
    @Autowired
    private CheckFeeListWriteMapper checkFeeListWriteMapper;
    @Autowired
    private CheckListWriteMapper checkListWriteMapper;
    @Autowired
    private UrgentWriteMapper urgentWriteMapper;
    @Autowired
    private UrgentReadMapper urgentReadMapper;
    @Autowired
    private BillWriteMapper billWriteMapper;
    @Autowired
    private BillDetailWriteMapper billDetailWriteMapper;
    @Autowired
    private BalanceSheetRecordWriteMapper balanceSheetRecordWriteMapper;
    @Autowired
    private OffrentConfirmWriteMapper offrentConfirmWriteMapper;
    @Autowired
    private RoomWriteMapper roomWriteMapper;
    @Autowired
    private PrepaymentService prepaymentService;
    @Autowired
    private BillDetailReadMapper billDetailReadMapper;
    @Autowired
    private IConfigurationService configurationService;
    @Autowired
    private CustomerCardWriteMapper customerCardWriteMapper;
    @Autowired
    private CustomerCardReadMapper customerCardReadMapper;

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = {BusinessException.class,
            LandseaBusinessException.class, Exception.class})
    public Integer createChangeRent(CreateOffLineContractsReq rqObj) throws LandseaException, BusinessException {
        Integer systemId = SecurityUtils.getCurrentLogin().getUserId();
        if (systemId == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.TOKEN_IS_NULL);
        }
        validateForInsert(rqObj);
        //取原始合同
        Contract oldContract = contractReadMapper.selectByPrimaryKey(rqObj.getContractId());
        Integer userId = rqObj.getUserId();
        //获取当前用户版本
        CustomerVersion customer = customerService.getNewVersion(userId);
        String version = customer==null ? "" : customer.getVersionNumber();
        RoomDetailReq aprt = roomService.searchRoomInfo(rqObj.getRoomId());
        if (aprt == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_APRT_ISNULL);
        }
        aprt.setRent(oldContract.getSalePrice());
        aprt.setPropertyFee(oldContract.getPropertyFee());
        aprt.getProject().setDepositWater(oldContract.getWaterDeposit());
        aprt.setOprType(LandeaConstants.ReRentType.CHANGE);
        contractOfflineService.calculationMonthRent(aprt, rqObj, null);
        // 新建合同
        Contract ctc = CreateOffLineContractsReq.convertDTOtoContract(rqObj);
        ctc.setOutDate(oldContract.getOutDate());
        ctc.setUserId(userId);
        // 房间信息
        ctc.setProjectId(aprt.getPrjId());
        ctc.setOffLine(true);
        ctc.setUserVersion(version);
        ctc.setOriginalPrice(oldContract.getSalePrice());//房间原价=B合同优惠后月租
        ctc.setOriginalWaterDeposit(oldContract.getWaterDeposit());//水费押金原价
        ctc.setSourceRentType(LandeaConstants.ReRentType.CHANGE);
        ctc.setRentType(LandeaConstants.ReRentType.CHANGE);
        ctc.setOriginalCId(rqObj.getContractId());
        ctc.setSource(oldContract.getSource());
        ctc.updateCommonInfo(systemId);

        //查看是否有授权码
        couponUsedService.checkUesdAuthCode(LandeaConstants.QueryUesdCodeType.CONTRACT,userId,rqObj.getAuthCodes());

        // 设置收取滞纳金、门锁时长
        Integer lateFeeDay = configurationService.getIntegerValue("SYS_TIM_FOR_LAT_FEE");
        Integer payLastDay = configurationService.getIntegerValue("PAY_LAST_DAY_TIME");
        ctc.setLatefeeDay(lateFeeDay);
        ctc.setLastPayDay(payLastDay);
        
        contractWriteMapper.insertSelective(ctc);
        //修改原始合同
        Contract oldContractMod = new Contract();
        oldContractMod.setId(oldContract.getId());
        oldContractMod.setRentType(LandeaConstants.ReRentType.CHANGE);
        oldContractMod.updateCommonInfo(systemId);
        contractWriteMapper.updateByPrimaryKeySelective(oldContractMod);

        if (ctc.getId() != null) {
            // 添加联系人信息
            if (rqObj.getUrgentDTO() != null) {
                Urgent urgent = UrgentDTO.fromDTOtoUrgent(rqObj.getUrgentDTO());
                urgent.setContractId(ctc.getId());
                urgent.updateCommonInfo(systemId);
                urgentWriteMapper.insertSelective(urgent);
            }
            //添加银行卡信息
            if(rqObj.getCardUserName()!=null){
                CustomerCard customerCard =CreateOffLineContractsReq.convertDTOtoCustomerCard(rqObj);
                customerCard.setSourceId(ctc.getId());
                customerCard.updateCommonInfo(systemId);
                customerCardWriteMapper.insertSelective(customerCard);
            }
            try {
                billService.createFirstBill(ctc.getId(),rqObj.getAuthCodes());
                // 生成pdf
                contractService.createPdf(ctc.getId());
            } catch (LandseaException e) {
                logger.error("生成pdf异常", e);
                throw LandseaException.createException(e.getErrorEnum());
            } catch (Exception e) {
                logger.error("生成pdf异常", e);
            }
        }
        return ctc.getId();
    }

    @Override
    public void createPreBill(Integer contractId) throws LandseaException {
        Date reRentDate = new Date();
        //查询该合同是否存在
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if (contract == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        if (!StringUtils.isEmpty(contract.getRentStatus())) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_RENTTYPE_ERROR);
        }
        //判断是否存在有效的预结算单，如存在则删除
        offrentPreBillService.deletePreBillByContractId(contract.getId());
        //新增结转单
        Integer preBillId =changeRentPreBillService.createPreBill(contract);
    }


    private void validateForInsert(CreateOffLineContractsReq req)throws LandseaException{
        if (req.getContractId() == null ) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_UPDATE_CONTRACTID_ISNULL);
        }
        if (req.getUserId() == null ) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_USERID_ISNULL);
        }
        if (req.getProjectId() == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_PROJECTID_ISNULL);
        }

        if (req.getRoomId() == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_ROOMID_ISNULL);
        }

        if (StringUtils.isEmpty(req.getPaymentMode())) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_PAYMENTMODE_ISNULL);
        }

        if (StringUtils.isEmpty(req.getLease())) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_LEASE_ISNULL);
        }

        if (req.getInDate() == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_INDATE_ISNULL);
        }

        if (req.getOutDate() == null) {
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_CREATE_OUTDATE_ISNULL);
        }
        //如果租期为其他 leaseM   leaseD 不能为空
        if(req.getLease().equals(LeaseCodeEnum.LEAS99.getCode())){
            if(req.getLeaseM()==null || req.getLeaseD()==null){
                throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_OFFLINE_LEASEMD_INDATE_INVALID);
            }
        }
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED,  rollbackFor = {LandseaException.class, Exception.class})
    public boolean cancleChangeRent(Integer contractId) throws LandseaException {
        boolean result=true;
        Contract contract = contractReadMapper.selectByPrimaryKey(contractId);
        if(contract==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_IS_NULL);
        }
        //合同状态只能为已签约
        /*if(!contract.getStatus().equals(ContractStatusCodeEnum.SIGN.getCode())){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_STATUS_IS_ERROR);
        }
        if(!StringUtils.isEmpty(contract.getRentStatus())){
            throw LandseaException.createException(LandseaErrorMessageEnum.CONTRACT_RENTTYPE_ERROR);
        }*/
        Integer roomId = contract.getRoomId();
        if(roomId == null){
            throw LandseaException.createException(LandseaErrorMessageEnum.ROOM_IS_NULL);
        }
        ContractDTO rerentContract = contractReadMapper.queryReRentContractDetail(contractId);
        if(rerentContract!=null){
            Bill parBill = billService.queryFirstBill(rerentContract.getId());
            if(!parBill.getBillStatus().equals(BillStatusEnum.BIST2.getCode())){
                if(rerentContract.getIsChapter()){
                    throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_CONTRACTB_IS_CHAPTER);
                }
            }else{
                throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_BILL_IS_PAY);
            }
        }else{
            //撤销退房申请
            offRentWriteMapper.deleteByContractId(contractId);
            return result;
           // throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_CONTRACTB_IS_NOTEXSIT);
        }
        //撤销退房申请
        offRentWriteMapper.deleteByContractId(contractId);
        //撤销退房交割单
        checkListWriteMapper.cancelCheckList(contractId, LandeaConstants.CheckType.UN_RENT);
        checkFeeListWriteMapper.cancelCheckFeeList(contractId, LandeaConstants.CheckType.UN_RENT);
        //撤销预结算单
        offrentPreBillService.cancelPreBill(contractId);
        //撤销预结算单的授权码使用记录
        PreOffrentBill preOffrentBill = offrentPreBillService.queryPreBillByContractId(contractId);
        if(preOffrentBill!=null){
            couponUsedService.deleteCouponUesd(preOffrentBill.getId(), LandeaConstants.QueryUesdCodeType.OFFRENT);
            //撤销退房确认
            offrentConfirmWriteMapper.deleteByContractIdPreId(contractId,preOffrentBill.getId());
        }
        if(contract.getStatus().equals(ContractStatusCodeEnum.END.getCode())){
            //撤销退房账单
            Bill offBill = billService.queryLastBill(contractId);
            if (offBill != null){
                if (offBill.getName().equals(ConstantChar.BILLING_OF_OFFRENT_BILL)){
                    //查询是否有账户余额
                    List<BillDetail> billDetails = billDetailReadMapper.getBillDetail(offBill.getId());
                    if(billDetails.size()>0){
                        Optional<BillDetail> billAccount = billDetails.stream().filter(e -> e.getType().equals(BillTypeEnum.CTBI22.getCode())).findFirst();
                        if (billAccount.isPresent()) {
                            //账户余额复存
                            prepaymentService.changeRentRebackMoney(contract.getUserId(), contract.getRoomId(), billAccount.get().getMoney());
                        }
                    }
                    billWriteMapper.deleteBillById(offBill.getId());
                    billDetailWriteMapper.deleteByBillId(offBill.getId());
                    //删除独立账单
                    Map<String,Object> paramMap = new HashMap<String,Object>();
                    paramMap.put("contractId", contractId);
                    paramMap.put("billId", offBill.getId());
                    paramMap.put("billType", BTypeEnum._BT2.getCode());
                    balanceSheetRecordWriteMapper.removeFirstBillBalance(paramMap);
                }
            }
        }

        //恢复A合同
        contractWriteMapper.updateRentTypeNull(contractId);
        //撤销B合同
        //删除续租B合同
        List<ContractNeedDelReq> contractList = new ArrayList<ContractNeedDelReq>();
        ContractNeedDelReq req = new ContractNeedDelReq();
        req.setRoomId(contract.getRoomId());
        req.setId(rerentContract.getId());
        contractList.add(req);
        // 删除账单
       // billService.deleteNoPayBill(contractList);
        // 删除合同
        contractService.deleteNoPayContracts(contractList);
        // 根据合同删除独立账单
        contractService.deleteBalanceByContract(contractList);
        //删除授权码使用记录
        couponUsedService.deleteCouponUesd(rerentContract.getId(), LandeaConstants.QueryUesdCodeType.CONTRACT);
        //恢复房源状态
        Room room = new Room();
        room.setId(contract.getRoomId());
        room.setSigned(true);
        room.setAppendStatus(RoomStatusCodeEnum.LRB3.getCode());
        room.updateCommonInfo(SecurityUtils.getCurrentLogin().getUserId());
        roomWriteMapper.updateByPrimaryKeySelective(room);
        
        // 恢复账户状态
        prepaymentService.updateAccountStatusByRoomAndUser(contract.getRoomId(),contract.getUserId(), AccountStatus.NORMAL);
        return result;
    }

    @Override
    public Object queryChangeContract(Integer contractId) {
        ContractDTO contractDTO = contractReadMapper.queryReRentContractDetail(contractId);
        if(contractDTO==null){
            return null;
        }
        contractDTO.setUrgentDTO(urgentReadMapper.queryDetailByContractId(contractDTO.getId(), null));
        //查询授权码使用信息
        HashMap map= new HashMap();
        map.put("mainId",contractDTO.getId());
        map.put("mainType",LandeaConstants.QueryUesdCodeType.CONTRACT);
        List<QueryCouponUesdDTO> codes= couponUsedService.querypPersonalCouponList(map);
        contractDTO.setAuthCodes(codes);
        //查询银行卡信息
        contractDTO.setCustomerCardDTO(customerCardReadMapper.queryCardInfo(map));
        return contractDTO;
    }

    @Override
    public void sysMoney(Integer contractId, Integer userBId) throws LandseaException {
        if(contractId==null || userBId==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.UPDATE_USER_PARAMS_ISNULL);
        }
        PreOffrentBill preOffrentBill = offrentPreBillService.queryPreBillByContractId(contractId);
        if(preOffrentBill==null){
            throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_PREBILL_IS_NOTEXIST);
        }
        if(preOffrentBill.getRefundAmount()<0){
            //余额结转至B账号
            //TOOD Junny
            //当前合同的退房账单变为已支付
            Bill bill = billService.queryLastBill(contractId);
            if(bill!=null){
                if(bill.getName().equals(ConstantChar.BILLING_OF_OFFRENT_BILL)){
                    Integer adminId = SecurityUtils.getCurrentLogin().getUserId();
                    //退房账单改为已支付
                    bill.setBillStatus(BillStatusEnum.BIST2.getCode());
                    bill.updateCommonInfo(adminId);
                    billWriteMapper.updateByPrimaryKeySelective(bill);
                }else{
                    throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_OFFRENTBILL_IS_NOTEXIST);
                }
            }else{
                throw LandseaException.createException(LandseaErrorMessageEnum.CHANGE_OFFRENTBILL_IS_NOTEXIST);
            }
        }
    }
}
